package com.siun.dk.util;

import com.sirun.ble.utils.AwLog;
import com.siun.dk.bean.CalibrationItemBean;

import java.util.List;

public class BleCalculatorUtil {

    public static void main() {
        // 测量数据: {距离, RSSI, 权重}
        double[][] measurements = {
                {1.0, -50.0, 1.0},  // 1米
                {2.0, -60.0, 0.8},  // 2米
                {3.0, -65.0, 0.6},  // 3米
                {5.0, -70.0, 0.4}   // 5米
        };

        double[] result = estimatePathLossParams(measurements);

        AwLog.d("Calibration main A (RSSI at 1m): " + result[0]);
        AwLog.d("Calibration main Path loss exponent n: " + result[1]);
    }

    public static double[] estimatePathLossParams(double[][] measurements) {
        // 转换为对数距离
        double[][] logData = new double[measurements.length][3];
        for (int i = 0; i < measurements.length; i++) {
            AwLog.d("Calibration estimatePathLossParams 转换前 i: " + i + " ,weight: " + measurements[i][2] + " ,distance: " + measurements[i][0] + " ,rssi: " + measurements[i][1]);
            logData[i][0] = Math.log10(measurements[i][0]); // log10(distance)
            logData[i][1] = measurements[i][1]; // RSSI
            logData[i][2] = measurements[i][2]; // weight
            AwLog.d("Calibration estimatePathLossParams 转换后 i: " + i + " ,weight: " + logData[i][2] + " ,distance: " + logData[i][0] + " ,rssi: " + logData[i][1]);
        }

        // 加权最小二乘法的变量
        double sumW = 0, sumWX = 0, sumWY = 0, sumWX2 = 0, sumWXY = 0;

        for (double[] point : logData) {
            double w = point[2];
            double x = point[0];
            double y = point[1];

            sumW += w;
            sumWX += w * x;
            sumWY += w * y;
            sumWX2 += w * x * x;
            sumWXY += w * x * y;
        }

        // 计算斜率和截距
        double denominator = sumW * sumWX2 - sumWX * sumWX;
        double A = (sumWX2 * sumWY - sumWX * sumWXY) / denominator;
        double slope = (sumW * sumWXY - sumWX * sumWY) / denominator;

        // 斜率 = -10n => n = -slope/10
        double n = -slope / 10.0;

        return new double[]{A, n};
    }

    // 在不同距离进行多次测量求平均n值
    public static double calculateAverageN(List<CalibrationItemBean> list) {
        double sum = 0;
        for (int i = 0; i < list.size(); i++) {
            AwLog.d("Calibration calculateAverageN i: " + i + " ,weight: " + list.get(i).getWeight() + " ,distance: " + list.get(i).getDistance() + " ,rssi: " + list.get(i).getRssi());
            sum += (list.get(i).getWeight() - list.get(i).getRssi()) / (10 * Math.log10(list.get(i).getDistance()));
            AwLog.d("Calibration sum : " + sum);
        }
        return sum / list.size();
    }
}